using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Forms;

namespace FB.WinForms.Controls
{
	/// <summary>
	/// The LinearGradientBrushDialog form is used by the <see cref="HtmlDropDownListItemsEditorUI"/>
	/// to enter the Brush tag with a type attribute of LinearGradient.
	/// </summary>
	public class LinearGradientBrushDialog : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Button buttonStartingColor;
		private System.Windows.Forms.Button buttonEndingColor;
		private System.Windows.Forms.Label labelSampleHeading;
		private System.Windows.Forms.Label labelAngle;
		private System.Windows.Forms.PictureBox pictureBoxSample;
		private System.Windows.Forms.Button buttonOK;
		private System.Windows.Forms.Button buttonCancel;
		private System.ComponentModel.Container components = null;

		private Color mStartColor = Color.Blue;
		private Color mEndColor = Color.Red;
		private float mAngle = 45;
		private System.Windows.Forms.NumericUpDown numericUpDownAngle;
		private string mStartTag = string.Empty;

		/// <summary>
		/// Initialise a new instance of the <see cref="LinearGradientBrushDialog"/> class.
		/// </summary>
		/// <param name="color1">A Color structure that represents the starting color for the gradient.</param>
		/// <param name="color2">A Color structure that represents the ending color for the gradient.</param>
		/// <param name="angle">The angle, measured in degrees clockwise from the x-axis, of the gradient's orientation line.</param>
		public LinearGradientBrushDialog(Color color1, Color color2, float angle)
		{
			InitializeComponent();

			StartColor = color1;
			EndColor = color2;
			Angle = angle;

			DrawSample(StartColor, EndColor, Angle);
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.buttonStartingColor = new System.Windows.Forms.Button();
			this.buttonEndingColor = new System.Windows.Forms.Button();
			this.labelSampleHeading = new System.Windows.Forms.Label();
			this.numericUpDownAngle = new System.Windows.Forms.NumericUpDown();
			this.labelAngle = new System.Windows.Forms.Label();
			this.pictureBoxSample = new System.Windows.Forms.PictureBox();
			this.buttonOK = new System.Windows.Forms.Button();
			this.buttonCancel = new System.Windows.Forms.Button();
			((System.ComponentModel.ISupportInitialize)(this.numericUpDownAngle)).BeginInit();
			this.SuspendLayout();
			// 
			// buttonStartingColor
			// 
			this.buttonStartingColor.Location = new System.Drawing.Point(8, 8);
			this.buttonStartingColor.Name = "buttonStartingColor";
			this.buttonStartingColor.Size = new System.Drawing.Size(88, 23);
			this.buttonStartingColor.TabIndex = 0;
			this.buttonStartingColor.Text = "Starting Color";
			this.buttonStartingColor.Click += new System.EventHandler(this.buttonStartingColor_Click);
			// 
			// buttonEndingColor
			// 
			this.buttonEndingColor.Location = new System.Drawing.Point(112, 8);
			this.buttonEndingColor.Name = "buttonEndingColor";
			this.buttonEndingColor.Size = new System.Drawing.Size(88, 23);
			this.buttonEndingColor.TabIndex = 1;
			this.buttonEndingColor.Text = "Ending Color";
			this.buttonEndingColor.Click += new System.EventHandler(this.buttonEndingColor_Click);
			// 
			// labelSampleHeading
			// 
			this.labelSampleHeading.Location = new System.Drawing.Point(0, 80);
			this.labelSampleHeading.Name = "labelSampleHeading";
			this.labelSampleHeading.Size = new System.Drawing.Size(48, 16);
			this.labelSampleHeading.TabIndex = 3;
			this.labelSampleHeading.Text = "Sample:";
			// 
			// numericUpDownAngle
			// 
			this.numericUpDownAngle.Increment = new System.Decimal(new int[] {
																				 5,
																				 0,
																				 0,
																				 0});
			this.numericUpDownAngle.Location = new System.Drawing.Point(104, 48);
			this.numericUpDownAngle.Maximum = new System.Decimal(new int[] {
																			   360,
																			   0,
																			   0,
																			   0});
			this.numericUpDownAngle.Name = "numericUpDownAngle";
			this.numericUpDownAngle.Size = new System.Drawing.Size(80, 20);
			this.numericUpDownAngle.TabIndex = 4;
			this.numericUpDownAngle.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
			// 
			// labelAngle
			// 
			this.labelAngle.Location = new System.Drawing.Point(48, 48);
			this.labelAngle.Name = "labelAngle";
			this.labelAngle.Size = new System.Drawing.Size(40, 23);
			this.labelAngle.TabIndex = 5;
			this.labelAngle.Text = "Angle:";
			// 
			// pictureBoxSample
			// 
			this.pictureBoxSample.Location = new System.Drawing.Point(8, 104);
			this.pictureBoxSample.Name = "pictureBoxSample";
			this.pictureBoxSample.Size = new System.Drawing.Size(192, 50);
			this.pictureBoxSample.TabIndex = 6;
			this.pictureBoxSample.TabStop = false;
			// 
			// buttonOK
			// 
			this.buttonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
			this.buttonOK.Location = new System.Drawing.Point(24, 168);
			this.buttonOK.Name = "buttonOK";
			this.buttonOK.TabIndex = 10;
			this.buttonOK.Text = "OK";
			// 
			// buttonCancel
			// 
			this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.buttonCancel.Location = new System.Drawing.Point(104, 168);
			this.buttonCancel.Name = "buttonCancel";
			this.buttonCancel.TabIndex = 9;
			this.buttonCancel.Text = "Cancel";
			// 
			// LinearGradientBrushDialog
			// 
			this.AcceptButton = this.buttonOK;
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.CancelButton = this.buttonCancel;
			this.ClientSize = new System.Drawing.Size(208, 198);
			this.ControlBox = false;
			this.Controls.Add(this.buttonOK);
			this.Controls.Add(this.buttonCancel);
			this.Controls.Add(this.pictureBoxSample);
			this.Controls.Add(this.labelAngle);
			this.Controls.Add(this.numericUpDownAngle);
			this.Controls.Add(this.labelSampleHeading);
			this.Controls.Add(this.buttonEndingColor);
			this.Controls.Add(this.buttonStartingColor);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
			this.MaximizeBox = false;
			this.MinimizeBox = false;
			this.Name = "LinearGradientBrushDialog";
			this.ShowInTaskbar = false;
			this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
			this.Text = "Linear Gradient Brush";
			((System.ComponentModel.ISupportInitialize)(this.numericUpDownAngle)).EndInit();
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The angle, measured in degrees clockwise from the x-axis, of the gradient's orientation line.
		/// </summary>
		public float Angle
		{
			get { return mAngle; }
			set 
			{ 
				mAngle = value; 
				mStartTag = string.Empty;
			}
		}

		/// <summary>
		/// A Color structure that represents the ending color for the gradient.
		/// </summary>
		public Color EndColor
		{
			get { return mEndColor; }
			set 
			{ 
				mEndColor = value; 
				mStartTag = string.Empty;
			}
		}

		/// <summary>
		/// The hexadecimal triplet that represents the ending color for the gradient.
		/// </summary>
		public string EndColorRGB
		{
			get { return String.Format(CultureInfo.InvariantCulture, "{0:X2}{1:X2}{2:X2}", EndColor.R, EndColor.G, EndColor.B); }
		}
			
		/// <summary>
		/// Gets the end tag of the Brush element.
		/// </summary>
		public string EndTag
		{
			get { return "</brush>"; }
		}

		/// <summary>
		/// A Color structure that represents the starting color for the gradient.
		/// </summary>
		public Color StartColor
		{
			get { return mStartColor; }
			set 
			{ 
				mStartColor = value; 
				mStartTag = string.Empty;
			}
		}

		/// <summary>
		/// The hexadecimal triplet that represents the starting color for the gradient.
		/// </summary>
		public string StartColorRGB
		{
			get { return String.Format(CultureInfo.InvariantCulture, "{0:X2}{1:X2}{2:X2}", StartColor.R, StartColor.G, StartColor.B); }
		}
			
		/// <summary>
		/// Gets the start tag of the Brush element.
		/// </summary>
		public string StartTag
		{
			get
			{
				if (mStartTag.Length == 0)
				{
					mStartTag = String.Format(CultureInfo.InvariantCulture, "<brush type=\"LinearGradient\" StartingColor=\"#{0}\" EndingColor=\"#{1}\" GradientAngle=\"{2}\">", StartColorRGB, EndColorRGB, Angle);
				}
				return mStartTag; 
			}
		}

		/// <summary>
		/// Handles the click event of the Starting Color button.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonStartingColor_Click(object sender, System.EventArgs e)
		{
			ColorDialog colorDialog = new ColorDialog();
			if (colorDialog.ShowDialog() == DialogResult.OK)
			{
				StartColor =  colorDialog.Color;
				DrawSample(StartColor, EndColor, Angle);
			}
		}

		/// <summary>
		/// Handles the click event of the Ending Color button.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonEndingColor_Click(object sender, System.EventArgs e)
		{
			ColorDialog colorDialog = new ColorDialog();
			if (colorDialog.ShowDialog() == DialogResult.OK)
			{
				EndColor =  colorDialog.Color;
				DrawSample(StartColor, EndColor, Angle);
			}
		}		

		/// <summary>
		/// Handles changes in value of the Angle NumericUpDown control.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void numericUpDown1_ValueChanged(object sender, System.EventArgs e)
		{
			Angle = (float)numericUpDownAngle.Value;
			DrawSample(StartColor, EndColor, Angle);
		}	

		/// <summary>
		/// Draws the text "Sample" in the selected linear gradient brush settings.
		/// </summary>
		/// <param name="color1">A Color structure that represents the starting color for the gradient. </param>
		/// <param name="color2">A Color structure that represents the ending color for the gradient.</param>
		/// <param name="angle">The angle, measured in degrees clockwise from the x-axis, of the gradient's orientation line.</param>
		private void DrawSample(Color color1, Color color2, float angle)
		{
			StringFormat lStringFormat = new StringFormat();
			Font lSampleFont;

			if (pictureBoxSample.Image == null)
			{
				pictureBoxSample.Image = new Bitmap(pictureBoxSample.Size.Width, pictureBoxSample.Size.Height);
			}
			using (Graphics lGraphics = Graphics.FromImage(pictureBoxSample.Image)) 
			{
				lStringFormat.LineAlignment = StringAlignment.Center;
				lStringFormat.Alignment = StringAlignment.Center;
				lSampleFont = new Font(FontFamily.GenericSansSerif, pictureBoxSample.Height, FontStyle.Regular, GraphicsUnit.Pixel);
				Brush lBrush = new LinearGradientBrush(new Rectangle(0, 0, pictureBoxSample.Size.Width, pictureBoxSample.Size.Height), color1, color2, angle);
				lGraphics.DrawString("Sample", lSampleFont, lBrush, new Rectangle(0, 0, pictureBoxSample.Size.Width, pictureBoxSample.Size.Height), lStringFormat);
				pictureBoxSample.Invalidate();
			}
		}
	}
}
